﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Evolution
{    
    class Evol
    {
        public int Size { get; private set; }//size of field
        public int CounterLevelCel { get; private set; }
        public int CounterLevelPredator { get; private set; }
        public int CounterLevelVegetarian { get; private set; }
        Cel[,] field = null;
        public Evol(int n) 
        { 
            Size = n;
            field = new Cel[n, n];
            CounterLevelCel = CounterLevelPredator = CounterLevelVegetarian = 0;
        }

        public void GenerateNewField()
        {
            Random r = new Random();
            for (int i = 0; i < Size; i++)
                for (int j = 0; j < Size; j++)
                {
                    switch (r.Next(0, 11))
                    {
                        case 0:
                            field[i, j] = new Cel(i, j);
                            break;
                        case 1:
                        case 2:
                        case 3:
                        case 4:
                        case 5:
                        case 6:
                        case 7:
                        case 8:
                        case 9:
                            field[i, j] = new Vegetarian(i, j);
                            break;
                        case 10:
                            field[i, j] = new Predator(i, j);
                            break;
                    }
                }
        }
        private void CloneFieldFrom(Evol E)
        {
            if (Size != E.Size)
            {
                this.Size = E.Size;
                field = new Cel[Size,Size];
            }
            for (int i = 0; i < Size; i++)
                for (int j = 0; j < Size; j++)            
                    field[i, j] = E.field[i, j].CopyTo();            
        }
        public void ShowField()
        {
            for (int i = 0; i < Size; i++)
            {
                for (int j = 0; j < Size; j++)               
                    field[i, j].Show();
                Console.WriteLine();
            }
            WriteLevel();
        }
        private string[] mySplit(string str)
        {
            string[] tmp = null;
            string buf = "";
            foreach (char c in str)
                if (MyConst.ABC.IndexOf(c) != -1)
                    buf += c.ToString();
            Size = (int)Math.Sqrt(buf.Length);
            tmp = new string[Size];

            for (int i = 0; i < Size; i++)
            {
                str = "";
                for (int j = 0; j < Size; j++)
                {
                    str += buf[i * Size + j].ToString();
                }
                tmp[i] = str;
            }
            return tmp;
        }
        public void LoadFieldFromFile(StreamReader reader)
        {
            string buf = reader.ReadToEnd();
            //string[] str = buf.Split('\n','\r');
            string[] str = mySplit(buf);
            Size = str.Length;
            field = new Cel[Size, Size];
            for (int i = 0; i < str.Length; i++)            
                for (int j=0;j<str[i].Length;j++)
                {
                    switch (str[i][j])
                    {
                        case ' ':
                            field[i, j] = new Cel(i, j);
                            break;
                        case '+':
                            field[i, j] = new Vegetarian(i, j);
                            break;
                        case '*':
                            field[i, j] = new Predator(i, j);
                            break;
                        default:
                            throw new Exception("Uncorrect the file!!!");
                    }
                }
        }
        public void SaveFieldToFile(StreamWriter writer)
        {
            for (int i = 0; i < Size; i++)
            {
                for (int j = 0; j < Size; j++)
                {
                    field[i, j].WriteToStream(writer);
                }
                writer.WriteLine();
            }
        }
        public void Update()
        {
            Evol tmp = new Evol(this.Size);
            tmp.CloneFieldFrom(this);
            for (int i = 0; i < Size; i++)
                for (int j = 0; j < Size; j++)
                    field[i, j].OneStep(this, ref tmp.field[i, j]);
            this.SynchronizationOfAttackTo(tmp);
            this.CloneFieldFrom(tmp);
            CountLevel();
            KillPredator();
            NullPredator();
        }
        private void SynchronizationOfAttackTo(Evol evol)
        {
            for (int i=0;i<Size;i++)
                for (int j = 0; j < Size; j++)
                {
                    if (field[i, j] is Predator && evol[i,j] is Predator)
                        if (((Predator)field[i, j]).isAttack)
                            ((Predator)evol.field[i, j]).isAttack = ((Predator)field[i, j]).isAttack;
                }
        }
        private void KillPredator()
        {
            for (int i = 0; i < Size; i++)
                for (int j = 0; j < Size; j++)
                {
                    if (field[i, j] is Predator)
                        if ((field[i, j].Level >= MyConst.PREDATORLIFE) && ((Predator)field[i,j]).isAttack == false)
                            field[i, j] = new Cel(i, j);
                }
        }
        private void NullPredator()
        {
            foreach (Cel c in field)
            {
                if (c is Predator) ((Predator)c).isAttack = false;
            }
        }
        private void CountLevel()
        {
            CounterLevelCel = CounterLevelPredator = CounterLevelVegetarian = 0;
            foreach (Cel c in field)
            {
                if (c is Predator)
                {
                    if (c.Level > CounterLevelPredator)
                        CounterLevelPredator = c.Level;
                }
                else if (c is Vegetarian)
                {
                    if (c.Level > CounterLevelVegetarian)
                        CounterLevelVegetarian = c.Level;
                }
                else
                    if (c.Level > CounterLevelCel)
                        CounterLevelCel = c.Level;
            }
        }
        public void WriteLevel()
        {
            Console.WriteLine();
            Console.WriteLine("Max level of Cel: " + CounterLevelCel);
            Console.WriteLine("Max level of Vegetarian: " + CounterLevelVegetarian);
            Console.WriteLine("Max level of Predator: " + CounterLevelPredator);
            Console.WriteLine();
        }
        public Cel this[int x, int y]
        {            
            get
            {  
                if (x >= Size || y >= Size) throw new IndexOutOfRangeException();
                return field[x,y];
            }
            set
            {
                if (x >= Size || y >= Size) throw new IndexOutOfRangeException();
                field[x, y] = value.CopyTo();
            }
        }
    }
}


